package com.ai.dmc.utils.remotecall;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.engine.ListenerManager;
import org.apache.commons.lang.StringUtils;

import com.ai.dmc.utils.remotecall.bean.Interface;
import com.ai.dmc.utils.remotecall.bean.Result;

/**
 * WebService客户端
 * 
 * @author Chongming
 */
public abstract class WsClient {
	
	protected SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmsssSSS");
	
	/**
	 * 调用WebService服务接口
	 * @param ifc 接口
	 * @param datas 报文数据
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public Result call(Interface ifc, String... datas) throws Exception {
		Result result = new Result();
		ListenerManager.defaultConfigurationContext = null;
		ServiceClient serviceClient = new ServiceClient();
		
		Options opts = new Options(); 
		opts.setTo(new EndpointReference(ifc.getServiceAddress()));
		opts.setProperty(Constants.Configuration.DISABLE_SOAP_ACTION, true);
		
		long timeOut = 10000;
		if (ifc.getTimeOut() > 0) {
			timeOut = ifc.getTimeOut();
		}
		opts.setTimeOutInMilliSeconds(timeOut);
		serviceClient.setOptions(opts);
		
		List<SOAPHeaderBlock> headers = createSoapHeaderDatas(ifc);
		if (null != headers) {
			for (SOAPHeaderBlock header : headers) {
				serviceClient.addHeader(header);
			}
		}
		
		OMElement res = serviceClient.sendReceive(createSoapBodyDatas(ifc, datas)); 
		Iterator<OMElement> ces = res.getChildElements();
		if (null != ces) {
			while (ces.hasNext()) {
				OMElement ce = ces.next();
				result.getDatas().add(ce.getText());
			}
		}
		
		long timeMillis = System.currentTimeMillis();
		result.setTime(timeMillis);
		result.setOprId(ifc.getSender() + "_" + ifc.getInterfaceName() + "_" + 
				dateFormat.format(new Date(timeMillis)));
		
		return result;
	}
	
	
	/**
	 * 创建SOAP Header信息
	 * @param ifc
	 * @return
	 */
	protected abstract List<SOAPHeaderBlock> createSoapHeaderDatas(Interface ifc);

	/**
	 * 创建SOAP Body数据
	 * @param ifc
	 * @param datas
	 * @return
	 */
	private OMElement createSoapBodyDatas(
			Interface ifc, String... datas) { 
		
		OMFactory oMFactory = OMAbstractFactory.getOMFactory(); 
		OMNamespace namespace = null;
		if (StringUtils.isNotBlank(ifc.getWsNameSpace())) {
			namespace = oMFactory.createOMNamespace(
					ifc.getWsNameSpace(), ifc.getWsPointName());
		}
		
		OMElement method = oMFactory.createOMElement(
				ifc.getInterfaceName(), namespace);
		
		String[] argNames = ifc.getArgNames();
		if (null != argNames && argNames.length > 0) {
			for (int i = 0; i < argNames.length; i++) {
				OMElement value = oMFactory.createOMElement(argNames[i], null); 
				if (datas.length > i) {
					value.setText(datas[i]); 
				}
				method.addChild(value); 
			}
		} else {
			for (int i = 0; i < datas.length; i++) {
				OMElement value = oMFactory.createOMElement("arg" + i, namespace); 
				value.setText(datas[i]); 
				method.addChild(value); 
			}
		}
		return method; 
	}
	
}
